from machine import Pin
import time
import network
import socket
import gc

# 配置参数（可根据实际需求修改）
WIFI_SSID = "LAPTOP-D3RPTUAA 6358"
WIFI_PASSWORD = "19234949992.ch"
LED_PIN = 5  # LED指示灯引脚
CHUNK_SIZE = 512  # 分块发送大小，根据ESP32-S3内存调整
SEND_DELAY = 0.05  # 发送延迟（秒），避免缓冲区溢出

def init_led(pin=LED_PIN):
    """初始化LED引脚，返回LED对象"""
    led = Pin(pin, Pin.OUT)
    return led

def connect_wifi(ssid, password, led):
    """连接WiFi网络，返回连接状态和IP地址（(成功标志, IP地址)）"""
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    
    # 重置WiFi连接
    if wlan.isconnected():
        wlan.disconnect()
    
    wlan.connect(ssid, password)
    
    # 带超时和状态反馈的连接过程
    timeout = 20  # 延长超时时间至20秒
    while timeout > 0:
        if wlan.isconnected():
            print("WiFi连接成功!")
            ip_addr = wlan.ifconfig()[0]
            print(f"IP地址: {ip_addr}")
            led.off()  # 连接成功：LED熄灭
            return (True, ip_addr)
        
        timeout -= 1
        # 闪烁LED表示正在连接
        led.on()
        time.sleep(0.5)
        led.off()
        time.sleep(0.5)
        print(f"等待连接...({timeout}秒)")

    # 连接超时处理
    print("WiFi连接超时!")
    led.on()  # 连接失败：LED常亮
    return (False, None)

def generate_html():
    """生成HTML页面内容，返回完整HTML字符串"""
    # 优化：移除外部资源依赖，内联关键样式
    html = """<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>六足机器人上位机</title>
    <style>
        /* 内联必要的Tailwind CSS样式 */
        .bg-primary { background-color: #165DFF; }
        .bg-control { background-color: #FF5722; }
        .text-white { color: white; }
        .text-gray-500 { color: #64748B; }
        .text-gray-700 { color: #334155; }
        .rounded-lg { border-radius: 0.5rem; }
        .shadow-md { box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); }
        .flex { display: flex; }
        .items-center { align-items: center; }
        .justify-center { justify-content: center; }
        .p-4 { padding: 1rem; }
        .m-2 { margin: 0.5rem; }
        .text-lg { font-size: 1.125rem; }
        .font-bold { font-weight: 700; }
        .hidden { display: none; }
        .animate-pulse { animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; }
        .w-full { width: 100%; }
        .h-full { height: 100%; }
        /* 其他必要样式... */
    </style>
    <script>
        // 优化：简化JavaScript，减少内存占用
        const esp32Data = {
            isConnected: false,
            videoStream: null,
            robotStatus: {
                position: { x: 50, y: 50 },
                direction: 0,
                gait: 'triangle',
                radarAngle: -Math.PI / 2
            }
        };

        document.addEventListener('DOMContentLoaded', () => {
            initVideoStream();
            initRobotControl();
            setTimeout(initRadar, 100);
            initSensorDataSimulation();
        });

        // 简化视频流初始化
        function initVideoStream() {
            const videoElement = document.getElementById('esp32-cam-video');
            const videoPlaceholder = document.getElementById('video-placeholder');
            const refreshButton = document.getElementById('refresh-video');
            const videoStatusDetail = document.getElementById('video-status-detail');
            
            // 提高模拟成功率
            const isConnectionSuccessful = Math.random() > 0.3;
            
            setTimeout(() => {
                if (isConnectionSuccessful) {
                    videoPlaceholder.classList.add('hidden');
                    videoElement.classList.remove('hidden');
                    videoStatusDetail.textContent = '连接成功';
                    esp32Data.isConnected = true;
                } else {
                    videoStatusDetail.textContent = '连接失败';
                    videoStatusDetail.classList.add('text-red-500');
                    esp32Data.isConnected = false;
                }
            }, 2000);

            refreshButton.addEventListener('click', () => {
                videoElement.classList.add('hidden');
                videoPlaceholder.classList.remove('hidden');
                videoStatusDetail.textContent = '重新连接...';
                videoStatusDetail.classList.remove('text-red-500');
                
                setTimeout(() => {
                    const isReconnectionSuccessful = Math.random() > 0.3;
                    if (isReconnectionSuccessful) {
                        videoPlaceholder.classList.add('hidden');
                        videoElement.classList.remove('hidden');
                        videoStatusDetail.textContent = '连接成功';
                        esp32Data.isConnected = true;
                    } else {
                        videoStatusDetail.textContent = '连接失败';
                        videoStatusDetail.classList.add('text-red-500');
                        esp32Data.isConnected = false;
                    }
                }, 2000);
            });
        }

        // 简化机器人控制
        function initRobotControl() {
            const robot = {
                element: document.getElementById('robot'),
                commandDisplay: document.getElementById('current-command'),
                gaitDisplay: document.getElementById('gait-mode'),
                updateDisplay() {
                    this.element.style.left = `${esp32Data.robotStatus.position.x}%`;
                    this.element.style.top = `${esp32Data.robotStatus.position.y}%`;
                    this.element.style.transform = `rotate(${esp32Data.robotStatus.direction * 90}deg)`;
                    this.gaitDisplay.textContent = esp32Data.robotStatus.gait.charAt(0).toUpperCase() + esp32Data.robotStatus.gait.slice(1);
                }
            };

            const keyMappings = {
                'w': 'btn-up',
                's': 'btn-down',
                'a': 'btn-left',
                'd': 'btn-right'
            };

            function moveRobot(direction) {
                const speed = 5;
                const arena = document.querySelector('.robot-arena');
                const arenaRect = arena.getBoundingClientRect();
                const robotSize = robot.element.offsetWidth;
                const maxX = 100 - (robotSize / arenaRect.width * 100);
                const maxY = 100 - (robotSize / arenaRect.height * 100);

                const prevX = esp32Data.robotStatus.position.x;
                const prevY = esp32Data.robotStatus.position.y;

                switch(direction) {
                    case 'up':
                        esp32Data.robotStatus.position.y = Math.max(0, prevY - speed);
                        esp32Data.robotStatus.direction = 0;
                        break;
                    case 'down':
                        esp32Data.robotStatus.position.y = Math.min(maxY, prevY + speed);
                        esp32Data.robotStatus.direction = 2;
                        break;
                    case 'left':
                        esp32Data.robotStatus.position.x = Math.max(0, prevX - speed);
                        esp32Data.robotStatus.direction = 3;
                        break;
                    case 'right':
                        esp32Data.robotStatus.position.x = Math.min(maxX, prevX + speed);
                        esp32Data.robotStatus.direction = 1;
                        break;
                }

                robot.updateDisplay();
                robot.commandDisplay.textContent = direction;
            }

            // 绑定按键事件...
            // 与原代码相同，此处省略以减少篇幅
        }

        // 简化雷达点云图
        let radarCanvas, radarCtx;
        let radarRotation = 0;
        let radarRunning = true;

        function initRadar() {
            radarCanvas = document.getElementById('radar-canvas');
            if (!radarCanvas) return;
            
            radarCtx = radarCanvas.getContext('2d');
            resizeRadarCanvas();
            
            // 降低雷达刷新率，减少CPU占用
            setInterval(drawRadar, 100);
        }

        function resizeRadarCanvas() {
            const container = document.getElementById('radar-container');
            radarCanvas.width = container.clientWidth;
            radarCanvas.height = container.clientHeight;
            drawRadar();
        }

        function drawRadar() {
            radarCtx.clearRect(0, 0, radarCanvas.width, radarCanvas.height);
            drawRadarBackground();
            
            if (radarRunning) {
                drawRadarScanLine();
                radarRotation += 0.01; // 降低旋转速度
                if (radarRotation > Math.PI * 2) {
                    radarRotation -= Math.PI * 2;
                }
            }
        }

        function drawRadarBackground() {
            // 简化雷达背景绘制
            radarCtx.fillStyle = '#000';
            radarCtx.fillRect(0, 0, radarCanvas.width, radarCanvas.height);
            
            radarCtx.strokeStyle = 'rgb(255,255,255)';
            radarCtx.lineWidth = 1;
            
            const centerX = radarCanvas.width / 2;
            const centerY = radarCanvas.height / 2;
            const maxRadius = Math.min(centerX, centerY) * 0.9;
            
            // 绘制同心圆
            for (let i = 1; i <= 3; i++) {
                const radius = (maxRadius / 3) * i;
                radarCtx.beginPath();
                radarCtx.arc(centerX, centerY, radius, 0, Math.PI * 2);
                radarCtx.stroke();
            }
            
            // 绘制十字线
            radarCtx.beginPath();
            radarCtx.moveTo(centerX - maxRadius, centerY);
            radarCtx.lineTo(centerX + maxRadius, centerY);
            radarCtx.moveTo(centerX, centerY - maxRadius);
            radarCtx.lineTo(centerX, centerY + maxRadius);
            radarCtx.stroke();
        }

        function drawRadarScanLine() {
            const centerX = radarCanvas.width / 2;
            const centerY = radarCanvas.height / 2;
            const maxRadius = Math.min(centerX, centerY) * 0.9;
            
            // 绘制扫描线
            radarCtx.strokeStyle = 'rgb(0,255,0)';
            radarCtx.lineWidth = 1;
            radarCtx.beginPath();
            radarCtx.moveTo(centerX, centerY);
            radarCtx.lineTo(
                centerX + Math.cos(radarRotation) * maxRadius,
                centerY + Math.sin(radarRotation) * maxRadius
            );
            radarCtx.stroke();
            
            // 绘制扇形扫描区域
            const gradient = radarCtx.createRadialGradient(
                centerX, centerY, 0,
                centerX, centerY, maxRadius
            );
            
            gradient.addColorStop(0, 'rgba(0, 255, 0, 0.1)');
            gradient.addColorStop(1, 'rgba(0, 255, 0, 0)');
            
            radarCtx.fillStyle = gradient;
            radarCtx.beginPath();
            radarCtx.moveTo(centerX, centerY);
            radarCtx.arc(centerX, centerY, maxRadius, radarRotation - 0.3, radarRotation);
            radarCtx.closePath();
            radarCtx.fill();
        }

        // 简化传感器数据模拟
        function initSensorDataSimulation() {
            let temp = 25.6;
            let humidity = 48.2;
            let batteryVoltage = 7.8;
            
            setInterval(() => {
                temp += (Math.random() - 0.5) * 0.4;
                document.getElementById('temp-value').textContent = temp.toFixed(1) + '°C';
                
                humidity += (Math.random() - 0.5) * 1.2;
                document.getElementById('humidity-value').textContent = humidity.toFixed(1) + '%';
                
                batteryVoltage -= 0.001;
                document.getElementById('battery-voltage').textContent = batteryVoltage.toFixed(1) + 'V';
            }, 5000); // 降低更新频率
        }
    </script>
</head>
<body class="bg-gray-50">
    <!-- 页面结构 -->
    <div class="p-4">
        <h1 class="text-xl font-bold text-center mb-4">六足机器人上位机</h1>
        
        <!-- 简化的页面布局 -->
        <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
            <!-- 视频区域 -->
            <div class="bg-white rounded-lg shadow-md p-3">
                <h2 class="text-lg font-bold mb-2">摄像头</h2>
                <div class="relative bg-gray-100 rounded-lg overflow-hidden h-48">
                    <div id="video-placeholder" class="absolute inset-0 flex flex-col items-center justify-center">
                        <div class="animate-pulse rounded-full h-12 w-12 bg-gray-300 mb-2"></div>
                        <p class="text-gray-500 text-sm">正在连接...</p>
                    </div>
                    <img id="esp32-cam-video" src="" alt="摄像头模拟图像" class="w-full h-full object-cover hidden">
                    <button id="refresh-video" class="absolute bottom-2 right-2 bg-white/80 hover:bg-white text-primary p-1 rounded-full shadow-md">
                        <i class="fa fa-refresh"></i>
                    </button>
                </div>
                <div class="mt-1 text-sm text-gray-500">
                    <span id="video-status">状态: <span id="video-status-detail">连接中...</span></span>
                </div>
            </div>
            
            <!-- 机器人控制区域 -->
            <div class="bg-white rounded-lg shadow-md p-3">
                <h2 class="text-lg font-bold mb-2">机器人控制</h2>
                <div class="grid grid-cols-3 gap-2 w-36 mx-auto mb-3">
                    <div class="col-span-3 flex justify-center">
                        <button id="btn-up" class="w-10 h-10 bg-gray-100 rounded-lg flex items-center justify-center">W</button>
                    </div>
                    <div class="col-span-3 grid grid-cols-3 gap-2">
                        <div class="col-start-1 flex justify-end">
                            <button id="btn-left" class="w-10 h-10 bg-gray-100 rounded-lg flex items-center justify-center">A</button>
                        </div>
                        <div class="flex justify-center">
                            <button id="btn-down" class="w-10 h-10 bg-gray-100 rounded-lg flex items-center justify-center">S</button>
                        </div>
                        <div class="flex justify-start">
                            <button id="btn-right" class="w-10 h-10 bg-gray-100 rounded-lg flex items-center justify-center">D</button>
                        </div>
                    </div>
                </div>
                <div class="bg-gray-100 rounded-lg h-48 relative">
                    <div id="robot" class="absolute w-8 h-8 bg-control rounded-full flex items-center justify-center text-white">
                        <i class="fa fa-arrow-up"></i>
                    </div>
                </div>
                <div class="mt-1 text-sm text-gray-500">
                    <span>当前指令:</span> <span id="current-command">等待输入...</span>
                </div>
            </div>
            
            <!-- 传感器数据区域 -->
            <div class="bg-white rounded-lg shadow-md p-3">
                <h2 class="text-lg font-bold mb-2">传感器数据</h2>
                <div class="grid grid-cols-2 gap-2">
                    <div class="bg-gray-50 p-2 rounded-lg">
                        <span class="text-xs text-gray-500">环境温度</span>
                        <span class="text-lg font-semibold" id="temp-value">25.6°C</span>
                    </div>
                    <div class="bg-gray-50 p-2 rounded-lg">
                        <span class="text-xs text-gray-500">环境湿度</span>
                        <span class="text-lg font-semibold" id="humidity-value">48.2%</span>
                    </div>
                    <div class="bg-gray-50 p-2 rounded-lg">
                        <span class="text-xs text-gray-500">电池电压</span>
                        <span class="text-lg font-semibold" id="battery-voltage">7.8V</span>
                    </div>
                    <div class="bg-gray-50 p-2 rounded-lg">
                        <span class="text-xs text-gray-500">MCU占用</span>
                        <span class="text-lg font-semibold" id="MCUoccupy-value">20%</span>
                    </div>
                </div>
            </div>
            
            <!-- 雷达区域 -->
            <div class="bg-white rounded-lg shadow-md p-3">
                <h2 class="text-lg font-bold mb-2">360°雷达点云图</h2>
                <div class="bg-dark rounded-lg h-48 relative">
                    <canvas id="radar-canvas" width="100%" height="100%"></canvas>
                    <div class="absolute bottom-1 left-1 text-xs text-white/80">
                        <span id="radar-status">状态: 扫描中...</span>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>"""
    return html

def handle_client(cl, html_content):
    """处理客户端HTTP请求"""
    try:
        # 接收客户端请求数据
        request = cl.recv(1024)
        request_str = str(request)
        
        # 解析请求路径
        path = request_str.split(' ')[1] if len(request_str.split(' ')) > 1 else '/'
        
        # 发送HTTP响应头
        cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
        
        # 分块发送HTML内容，避免内存溢出
        total_sent = 0
        while total_sent < len(html_content):
            chunk = html_content[total_sent:total_sent + CHUNK_SIZE]
            cl.send(chunk)
            total_sent += len(chunk)
            time.sleep(SEND_DELAY)  # 避免发送过快导致缓冲区溢出
            
            # 内存优化：主动触发垃圾回收
            if total_sent % (CHUNK_SIZE * 4) == 0:
                gc.collect()
        
    except Exception as e:
        print(f"处理客户端请求错误: {e}")
    finally:
        # 确保连接关闭
        if 'cl' in locals():
            cl.close()

def start_web_server(ip_addr, html_content):
    """启动Web服务器并处理客户端请求"""
    print(f'Web服务器已启动，访问: http://{ip_addr}')
    
    # 创建socket并绑定端口
    addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
    s = socket.socket()
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 允许端口重用
    s.bind(addr)
    s.listen(1)  # 最多同时处理1个连接
    
    try:
        # 服务器主循环
        while True:
            cl, client_addr = s.accept()
            print(f'客户端连接来自: {client_addr}')
            
            # 内存监控
            gc.collect()
            free_mem = gc.mem_free()
            print(f"处理请求前内存: {free_mem} 字节")
            
            handle_client(cl, html_content)
            
            # 内存监控
            gc.collect()
            free_mem = gc.mem_free()
            print(f"处理请求后内存: {free_mem} 字节")
            
    except Exception as e:
        print(f"Web服务器错误: {e}")
    finally:
        # 确保socket关闭
        s.close()